import os
import uuid
from datetime import datetime
from werkzeug.utils import safe_join
from flask import jsonify, request, Response, send_from_directory
import time
from config import ALLOWED_EXTENSIONS, DEFAULT_ROOM_ID
from rating_system import load_movie_ratings

# 存储分片上传的信息
chunk_uploads = {}

# 存储房间和视频信息
room_info = {
    'video_path': None,
    'video_filename': None,
    'status': 'waiting',  # waiting, playing, paused
    'current_time': 0,
    'created_at': datetime.now().isoformat()
}

# 检查文件类型是否允许
def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

# 初始化分片上传
def init_upload_handler(app):
    """初始化分片上传，创建文件标识"""
    try:
        data = request.get_json()
        if not data or 'filename' not in data or 'total_chunks' not in data:
            return jsonify({'error': '缺少必要参数'}), 400
        
        filename = data['filename']
        total_chunks = data['total_chunks']
        
        # 检查文件类型
        if not allowed_file(filename):
            return jsonify({'error': '不支持的文件类型'}), 400
        
        # 生成文件ID
        file_id = str(uuid.uuid4())
        
        # 存储上传信息
        chunk_uploads[file_id] = {
            'chunks': {},
            'total_chunks': total_chunks,
            'filename': filename,
            'created_at': datetime.now().isoformat()
        }
        
        return jsonify({
            'success': True,
            'file_id': file_id,
            'message': '上传初始化成功'
        })
    except Exception as e:
        print(f"初始化上传错误: {str(e)}")
        return jsonify({'error': f'初始化上传失败: {str(e)}'}), 500

# 处理分片上传
def upload_chunk_handler(app):
    """接收文件分片"""
    try:
        file_id = request.form.get('file_id')
        chunk_index = request.form.get('chunk_index', type=int)
        
        if not file_id or chunk_index is None or file_id not in chunk_uploads:
            return jsonify({'error': '无效的请求参数'}), 400
        
        if 'chunk' not in request.files:
            return jsonify({'error': '没有分片文件'}), 400
        
        chunk_file = request.files['chunk']
        
        # 创建分片存储目录
        chunks_dir = safe_join(app.config['UPLOAD_FOLDER'], 'chunks')
        os.makedirs(chunks_dir, exist_ok=True)
        
        # 保存分片
        chunk_filename = f"{file_id}_{chunk_index}.chunk"
        chunk_path = safe_join(chunks_dir, chunk_filename)
        
        # 流式写入分片
        chunk_size = 8192
        with open(chunk_path, 'wb') as f:
            while True:
                chunk = chunk_file.read(chunk_size)
                if not chunk:
                    break
                f.write(chunk)
        
        # 更新分片信息
        chunk_uploads[file_id]['chunks'][chunk_index] = chunk_path
        
        # 检查是否所有分片都已上传
        is_complete = len(chunk_uploads[file_id]['chunks']) == chunk_uploads[file_id]['total_chunks']
        
        return jsonify({
            'success': True,
            'chunk_index': chunk_index,
            'total_received': len(chunk_uploads[file_id]['chunks']),
            'total_chunks': chunk_uploads[file_id]['total_chunks'],
            'is_complete': is_complete
        })
    except Exception as e:
        print(f"上传分片错误: {str(e)}")
        return jsonify({'error': f'分片上传失败: {str(e)}'}), 500

# 完成上传，合并分片
def complete_upload_handler(app, socketio):
    """完成上传，合并分片"""
    try:
        data = request.get_json()
        if not data or 'file_id' not in data:
            return jsonify({'error': '缺少必要参数'}), 400
        
        file_id = data['file_id']
        if file_id not in chunk_uploads:
            return jsonify({'error': '无效的文件ID'}), 400
        
        upload_info = chunk_uploads[file_id]
        
        # 检查是否所有分片都已上传
        if len(upload_info['chunks']) != upload_info['total_chunks']:
            return jsonify({'error': '分片不完整，无法合并'}), 400
        
        # 准备合并文件
        final_filename = f"{upload_info['filename']}"
        final_path = safe_join(app.config['UPLOAD_FOLDER'], final_filename)
        
        # 确保目录存在
        os.makedirs(os.path.dirname(final_path), exist_ok=True)
        
        # 合并分片
        with open(final_path, 'wb') as final_file:
            for i in range(upload_info['total_chunks']):
                if i in upload_info['chunks']:
                    chunk_path = upload_info['chunks'][i]
                    with open(chunk_path, 'rb') as chunk_file:
                        final_file.write(chunk_file.read())
                    # 删除已合并的分片
                    os.remove(chunk_path)
        
        print(f"文件合并完成: {upload_info['filename']}")
        
        # 更新房间信息
        room_info['video_path'] = final_path
        room_info['video_filename'] = upload_info['filename']
        
        # 评分将从用户文件实时计算，无需初始化记录
        
        # 加载该电影的评分数据
        movie_ratings = load_movie_ratings(upload_info['filename'])
        
        # 通知房间内的其他用户
        socketio.emit('video_uploaded', {
            'filename': upload_info['filename']
        }, room=DEFAULT_ROOM_ID)
        
        # 立即广播该电影的评分
        socketio.emit('rating_update', movie_ratings, room=DEFAULT_ROOM_ID)
        
        # 清理上传信息
        del chunk_uploads[file_id]
        
        # 返回JSON响应并确保内容类型正确
        response = jsonify({
            'success': True,
            'filename': upload_info['filename'],
            'message': '文件上传完成'
        })
        response.headers['Content-Type'] = 'application/json'
        return response
    except Exception as e:
        print(f"合并文件错误: {str(e)}")
        # 返回JSON错误响应并确保内容类型正确
        error_response = jsonify({'error': f'文件合并失败: {str(e)}'})
        error_response.headers['Content-Type'] = 'application/json'
        return error_response, 500

# 列出所有可用视频文件
def list_videos_handler(app):
    """列出所有可用的视频文件"""
    try:
        videos = []
        uploads_dir = app.config['UPLOAD_FOLDER']
        
        if not os.path.exists(uploads_dir):
            return jsonify({'success': True, 'videos': videos})
        
        # 遍历上传目录，找出所有视频文件
        for filename in os.listdir(uploads_dir):
            if allowed_file(filename) and os.path.isfile(os.path.join(uploads_dir, filename)):
                videos.append({
                    'filename': filename,
                    'size': os.path.getsize(os.path.join(uploads_dir, filename))
                })
        
        # 按文件名排序
        videos.sort(key=lambda x: x['filename'])
        
        return jsonify({'success': True, 'videos': videos})
    except Exception as e:
        print(f"列出视频文件错误: {str(e)}")
        return jsonify({'error': f'列出视频文件失败: {str(e)}'}), 500

# 选择视频进行播放
def select_video_handler(app, socketio):
    """选择一个已上传的视频进行播放"""
    try:
        data = request.get_json()
        if not data or 'filename' not in data:
            return jsonify({'error': '缺少必要参数'}), 400
        
        filename = data['filename']
        filepath = safe_join(app.config['UPLOAD_FOLDER'], filename)
        
        # 检查文件是否存在且为视频文件
        if not os.path.exists(filepath) or not allowed_file(filename):
            return jsonify({'error': '视频文件不存在或格式不支持'}), 404
        
        # 更新房间信息
        room_info['video_path'] = filepath
        room_info['video_filename'] = filename
        room_info['status'] = 'paused'
        room_info['current_time'] = 0
        
        # 评分将从用户文件实时计算，无需初始化记录
        
        # 加载该电影的评分数据
        movie_ratings = load_movie_ratings(filename)
        
        # 通知房间内的所有用户
        socketio.emit('video_uploaded', {
            'filename': filename
        }, room=DEFAULT_ROOM_ID)
        
        # 立即广播该电影的评分
        socketio.emit('rating_update', movie_ratings, room=DEFAULT_ROOM_ID)
        
        return jsonify({
            'success': True,
            'filename': filename,
            'message': '视频选择成功'
        })
    except Exception as e:
        print(f"选择视频错误: {str(e)}")
        return jsonify({'error': f'选择视频失败: {str(e)}'}), 500

# 流式传输视频文件
def serve_video_handler(app, filename):
    """流式传输视频文件，支持进度条拖动"""
    try:
        # 使用safe_join确保安全访问
        filepath = safe_join(app.config['UPLOAD_FOLDER'], filename)
        
        # 检查文件是否存在
        if not os.path.exists(filepath):
            return jsonify({'error': '视频文件不存在'}), 404
        
        # 获取文件大小
        file_size = os.path.getsize(filepath)
        
        # 获取Range头
        range_header = request.headers.get('Range', None)
        
        # 如果没有Range头，返回整个文件
        if not range_header:
            return send_from_directory(os.path.dirname(filepath), os.path.basename(filepath))
        
        # 解析Range头
        try:
            start, end = range_header.strip().split('=')[1].split('-')
            start = int(start)
            end = int(end) if end else file_size - 1
        except:
            start = 0
            end = file_size - 1
        
        # 确保范围有效
        if start >= file_size or end >= file_size:
            return Response("Range Not Satisfiable", status=416)
        
        # 计算内容长度
        content_length = end - start + 1
        
        # 设置响应头
        headers = {
            'Content-Range': f'bytes {start}-{end}/{file_size}',
            'Accept-Ranges': 'bytes',
            'Content-Length': content_length,
            'Content-Type': 'video/mp4'
        }
        
        # 以二进制模式打开文件并读取指定范围
        def generate():
            with open(filepath, 'rb') as f:
                f.seek(start)
                remaining = content_length
                while remaining > 0:
                    chunk_size = min(8192, remaining)
                    data = f.read(chunk_size)
                    if not data:
                        break
                    yield data
                    remaining -= chunk_size
                    # 避免CPU占用过高
                    time.sleep(0.001)
        
        # 返回部分内容
        return Response(generate(), 206, headers)
    except Exception as e:
        print(f"视频文件访问错误: {str(e)}")
        return jsonify({'error': '视频文件无法访问'}), 404